// Copyright Epic Games, Inc. All Rights Reserved.

#include "LyraCameraComponent.h"

#include "Engine/Canvas.h"
#include "Engine/Engine.h"
#include "GameFramework/Pawn.h"
#include "GameFramework/PlayerController.h"
#include "LyraCameraMode.h"

#include UE_INLINE_GENERATED_CPP_BY_NAME(LyraCameraComponent)


ULyraCameraComponent::ULyraCameraComponent(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer)
{
	CameraModeStack = nullptr; // 初始化相机模式堆栈为空
	FieldOfViewOffset = 0.0f; // 初始化视野偏移为0
}

void ULyraCameraComponent::OnRegister()
{
	Super::OnRegister(); // 调用父类的OnRegister

	if (!CameraModeStack) // 如果相机模式堆栈不存在
	{
		CameraModeStack = NewObject<ULyraCameraModeStack>(this); // 创建新的相机模式堆栈对象
		check(CameraModeStack); // 检查堆栈是否创建成功
	}
}

void ULyraCameraComponent::GetCameraView(float DeltaTime, FMinimalViewInfo& DesiredView)
{
	check(CameraModeStack); // 确保相机模式堆栈有效

	UpdateCameraModes(); // 更新相机模式

	FLyraCameraModeView CameraModeView; // 声明相机模式视图
	CameraModeStack->EvaluateStack(DeltaTime, CameraModeView); // 评估堆栈并获取相机模式视图

	// 保持玩家控制器与最新视图同步。
	if (APawn* TargetPawn = Cast<APawn>(GetTargetActor())) // 如果目标Actor是Pawn
	{
		if (APlayerController* PC = TargetPawn->GetController<APlayerController>()) // 获取玩家控制器
		{
			PC->SetControlRotation(CameraModeView.ControlRotation); // 设置控制器的控制旋转
		}
	}

	// 应用添加到视野字段的任何偏移。
	CameraModeView.FieldOfView += FieldOfViewOffset; // 增加视野偏移
	FieldOfViewOffset = 0.0f; // 重置视野偏移

	// 保持相机组件与最新视图同步。
	SetWorldLocationAndRotation(CameraModeView.Location, CameraModeView.Rotation); // 设置组件的位置和旋转
	FieldOfView = CameraModeView.FieldOfView; // 设置视野

	// 填充期望的视图。
	DesiredView.Location = CameraModeView.Location; // 设置期望位置
	DesiredView.Rotation = CameraModeView.Rotation; // 设置期望旋转
	DesiredView.FOV = CameraModeView.FieldOfView; // 设置期望视野
	DesiredView.OrthoWidth = OrthoWidth; // 设置正交宽度
	DesiredView.OrthoNearClipPlane = OrthoNearClipPlane; // 设置正交近裁剪平面
	DesiredView.OrthoFarClipPlane = OrthoFarClipPlane; // 设置正交远裁剪平面
	DesiredView.AspectRatio = AspectRatio; // 设置宽高比
	DesiredView.bConstrainAspectRatio = bConstrainAspectRatio; // 设置是否约束宽高比
	DesiredView.bUseFieldOfViewForLOD = bUseFieldOfViewForLOD; // 设置是否使用视野进行LOD计算
	DesiredView.ProjectionMode = ProjectionMode; // 设置投影模式

	// 查看CameraActor是否想要覆盖使用的后期处理设置。
	DesiredView.PostProcessBlendWeight = PostProcessBlendWeight; // 设置后期处理混合权重
	if (PostProcessBlendWeight > 0.0f) // 如果后期处理混合权重大于0
	{
		DesiredView.PostProcessSettings = PostProcessSettings; // 设置后期处理设置
	}


	if (IsXRHeadTrackedCamera()) // 如果是XR头戴式追踪相机
	{
		// 在XR中，上述大部分相机行为无关紧要，但后期处理设置并非如此。
		Super::GetCameraView(DeltaTime, DesiredView); // 调用父类的GetCameraView
	}
}

void ULyraCameraComponent::UpdateCameraModes()
{
	check(CameraModeStack); // 确保相机模式堆栈有效

	if (CameraModeStack->IsStackActivate()) // 如果堆栈已激活
	{
		if (DetermineCameraModeDelegate.IsBound()) // 如果委托已绑定
		{
			if (const TSubclassOf<ULyraCameraMode> CameraMode = DetermineCameraModeDelegate.Execute()) // 执行委托获取相机模式
			{
				CameraModeStack->PushCameraMode(CameraMode); // 将相机模式推入堆栈
			}
		}
	}
}

void ULyraCameraComponent::DrawDebug(UCanvas* Canvas) const
{
	check(Canvas); // 确保Canvas有效

	FDisplayDebugManager& DisplayDebugManager = Canvas->DisplayDebugManager; // 获取调试显示管理器

	DisplayDebugManager.SetFont(GEngine->GetSmallFont()); // 设置字体
	DisplayDebugManager.SetDrawColor(FColor::Yellow); // 设置绘制颜色为黄色
	DisplayDebugManager.DrawString(FString::Printf(TEXT("LyraCameraComponent: %s"), *GetNameSafe(GetTargetActor()))); // 绘制相机组件信息

	DisplayDebugManager.SetDrawColor(FColor::White); // 设置绘制颜色为白色
	DisplayDebugManager.DrawString(FString::Printf(TEXT("   Location: %s"), *GetComponentLocation().ToCompactString())); // 绘制位置信息
	DisplayDebugManager.DrawString(FString::Printf(TEXT("   Rotation: %s"), *GetComponentRotation().ToCompactString())); // 绘制旋转信息
	DisplayDebugManager.DrawString(FString::Printf(TEXT("   FOV: %f"), FieldOfView)); // 绘制视野信息

	check(CameraModeStack); // 确保相机模式堆栈有效
	CameraModeStack->DrawDebug(Canvas); // 绘制相机模式堆栈的调试信息
}

void ULyraCameraComponent::GetBlendInfo(float& OutWeightOfTopLayer, FGameplayTag& OutTagOfTopLayer) const
{
	check(CameraModeStack); // 确保相机模式堆栈有效
	CameraModeStack->GetBlendInfo(/*out*/ OutWeightOfTopLayer, /*out*/ OutTagOfTopLayer); // 从堆栈获取混合信息
}